// --------------------------------------------------------------------------------------------------------------------
// <copyright file="OnPremisesAdapterTest.cs" company="">
//   
// </copyright>
// --------------------------------------------------------------------------------------------------------------------
namespace Tests
{
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;

    using ExecutionTool.Common;
    using ExecutionTool.CopyOnPremises;
    using ExecutionTool.Profile;

    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    using Moq;

    using Timer = System.Timers.Timer;

    [TestClass]
    public class OnPremisesAdapterTest
    {
        #region Constants

        private const int BlockSize = 1024;

        #endregion

        #region Static Fields

        private static readonly object writeLocker = new object();

        #endregion

        #region Public Methods and Operators

        [TestMethod]
        public void CanAttachMetadata()
        {
            const string DataFile = "CanAttachMetadata.txt";
            var loggerMock = new Mock<LogWriter>();
            var adapter = new OnPremisesAdapter(loggerMock.Object);

            var data = new Dictionary<string, string> { { "Name", "Jack" }, { "Gender", "Male" } };

            adapter.SetMetadata(DataFile, data);
            var dataOut = adapter.GetMetadata(DataFile);

            Assert.AreEqual(data.Count, dataOut.Count);

            foreach (var pair in dataOut)
            {
                Assert.AreEqual(data[pair.Key], pair.Value);
            }
        }

        [TestMethod]
        public void CanListBlobsUnderFolder()
        {
            var assembly = Assembly.GetExecutingAssembly();

            var loggerMock = new Mock<LogWriter>();
            var adapter = new OnPremisesAdapter(loggerMock.Object);
            var result = adapter.ListBlobs(Path.GetDirectoryName(assembly.Location));

            foreach (var fileInfo in result)
            {
                Console.WriteLine(fileInfo.FullName + " [" + fileInfo.CreationTimeUtc + "]");
            }
        }

        [TestMethod]
        public void CanReadWriteAds()
        {
            const string DataFile = "CanReadWriteAds.txt";
            const string AdsName = "SqlAzureDataProtector.metadata";

            using (var writer = new StreamWriter(DataFile))
            {
                writer.Write("This is a test.");
            }

            var builder = new StringBuilder();
            var metadata = new Dictionary<string, string> { { "DatabaseName", "dbname" }, { "Edition", "Web" }, { "MaxSizeInGb", "1GB" } };

            foreach (var pair in metadata)
            {
                builder.Append(pair.Key).Append("\t").Append(pair.Value).AppendLine();
            }

            ////Console.WriteLine(builder);
            AdsFile.Write(builder.ToString(), DataFile, AdsName);
            var stream = AdsFile.Read(DataFile, AdsName);

            ////Console.WriteLine(stream);
            Assert.AreEqual(builder.ToString(), stream);
        }

        [TestMethod]
        public void CanTestConnection()
        {
            var loggerMock = new Mock<LogWriter>();
            var adapter = new OnPremisesAdapter(loggerMock.Object);
            adapter.TestConnection(new OnPremisesLocation { Location = @"\\jackma\temp" });
        }

        [TestMethod]
        public void TestFileStream()
        {
            var tasks = new List<Task>();
            for (var i = 0; i < 5; i++)
            {
                var j = i;
                var t = Task.Factory.StartNew(
                    () =>
                        {
                            var data = this.GenerateData((char)(j + 'A'));
                            this.Write(data, j);
                        });

                tasks.Add(t);
            }

            Task.WaitAll(tasks.ToArray());
        }

        [TestMethod]
        public void TestFileStreamReadWrite()
        {
            const string DataFile = "data.txt";

            using (var stream = File.Open(DataFile, FileMode.Create, FileAccess.ReadWrite))
            {
                var count = 0;
                var e = new ManualResetEvent(false);
                var timer = new Timer(100);
                timer.Elapsed += (sender, args) =>
                    {
                        if (++count >= 50)
                        {
                            timer.Dispose();
                            e.Set();
                        }

                        stream.Seek(stream.Length, SeekOrigin.Begin);
                        stream.WriteByte(10);
                    };
                timer.Enabled = true;

                var timer2 = new Timer(200);
                timer2.Elapsed += (sender, args) =>
                    {
                        var info = new FileInfo(DataFile);
                        Console.WriteLine(info.Length);
                    };
                timer2.Enabled = true;

                e.WaitOne();
                timer2.Dispose();
            }
        }

        #endregion

        #region Methods

        private byte[] GenerateData(char seed)
        {
            var dataString = new string(seed, BlockSize);
            var data = Encoding.UTF8.GetBytes(dataString);

            Console.WriteLine(data.Length);
            Console.WriteLine(data[0]);
            return data;
        }

        private void Write(byte[] data, int index)
        {
            lock (writeLocker)
            {
                using (var s = File.OpenWrite(@"\\jackma\temp\unittest.txt"))
                {
                    s.Seek(BlockSize * index, SeekOrigin.Begin);
                    s.Write(data, 0, data.Length);
                }
            }
        }

        #endregion
    }
}
